<?php
/**
 * Created by PhpStorm.
 * User: guokunsheng
 * Date: 2018/6/13
 * Time: 11:45
 */

namespace App\Models\CacheModel;

use App\Models\CacheModel\lucky\AppUserLuckyChangeRecord;
use app\common\lib\exception\ApiException;
use app\common\lib\util\Time;
use App\Models\Api\BaseCache;
use Exception;
use think\Log;
use AstroTool\Cache\CacheManage;

/**
 * 运势日记模型类
 * Class FortuneNote
 * @package App\Models\Api
 */
class FortuneNote extends BaseCache
{
    protected $table = 'wechat_backup_07_18_14_43_00.app_fortune_note';
    protected $cacheModel = 'fortune.fortune_day_note';
    protected $cacheIdKey = 'id';
    protected $pageLimit = 15;

    /**
     * 添加日记
     * @param $data
     * @return int
     * @throws Exception
     */
    public function SaveData($data)
    {
        try
        {
            $uid = $data['uid'];
            $id = $this->allowField(true)->insertGetId($data);
            $this->rmCache($uid, $id, $data['tids'] ?? []);
        }
        catch (\Exception $e)
        {
            Log::write('FortuneNote model => ()异常：' . $e->getMessage() . '失败信息：' . $e->getFile() . ':' . $e->getLine(), 'error', true);
            return 0;
        }
        return $id;
    }

    /**
     * 更新日记
     * @param $id
     * @param $data
     * @return bool
     * @throws Exception
     */
    public function UpdateData($id, $data)
    {
        try
        {
            $this->where(['id' => $id])->update($data);
            CacheManage::getInstance()->setCacheConfig($this->cacheModel, $id)->rmCache();
        }
        catch (\Exception $e)
        {
            Log::write('FortuneNote model => ()异常：' . $e->getMessage() . '失败信息：' . $e->getFile() . ':' . $e->getLine(), 'error', true);
            return false;
        }
        return true;
    }

    /**
     * 删除日记
     * @param $id
     * @param $uid
     * @return bool
     * @throws Exception
     */
    public function DeleteData($id, $uid)
    {
        try
        {
            $info = $this->getInfoById($id, ['uid', 'tids']);
            if (!$info || $info['uid'] != $uid)
            {
                throw  new ApiException('服务异常,请稍后重试');
            }
            $this->where(['id' => $id])->update(['status' => -1]);
            $this->rmCache($uid, $id, $info['tids']);
        }
        catch (\Exception $e)
        {
            Log::write('FortuneNote model => ()异常：' . $e->getMessage() . '失败信息：' . $e->getFile() . ':' . $e->getLine(), 'error', true);
            return false;
        }
        return true;
    }

    /**
     * 更新缓存
     * @param $uid
     * @param $id
     * @param $tids
     * @return void
     * @throws Exception
     */
    protected function rmCache($uid, $id, $tids)
    {
        if (!empty($tids))
        {
            CacheManage::getInstance()->setCacheConfig($this->cacheModel, $uid)->setListKeyType(2)->rmCache('list');
            CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('all_ids', "$uid:2")->rmCache('all_ids');
        } else
        {
            CacheManage::getInstance()->setCacheConfig($this->cacheModel, $uid)->setListKeyType(1)->rmCache('list');
            CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('all_ids', "$uid:1")->rmCache('all_ids');
        }
        CacheManage::getInstance()->setCacheConfig($this->cacheModel, $uid)->setListKeyType(0)->rmCache('list');//笔记列表
        CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('all_ids', "$uid:0")->rmCache('all_ids');//所有笔记
        //删除日记详情缓存
        CacheManage::getInstance()->setCacheConfig($this->cacheModel, $id)->rmCache();
    }

    /**
     * 获取用户运势笔记列表,分页
     * @param $uid
     * @param int $type 0=>全部 1=>运势笔记旧版 2=>心情笔记版
     * @return array|mixed
     * @throws Exception
     */
    public function getNotePageAll($uid, int $type)
    {
        return $this->getListPage($uid, 'id', [], $type);
    }

    /**
     * 获取用户所有日记id
     * @param $uid
     * @param $type 0=>全部 1=>运势笔记旧版 2=>心情笔记版
     * @return array
     * @throws Exception
     */
    public function getNoteLists($uid, $type)
    {
        $ids = CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('all_ids', "{$uid}:{$type}")->ZsGetIocData('all_ids', function () use ($type, $uid)
        {
            try
            {
                $where['uid'] = $uid;
                if ($type === 1)
                {
                    $where['tids'] = '';
                } elseif ($type === 2)
                {
                    $where['tids'] = ['NEQ', ''];
                }
                $where['status'] = ['>', -1];
                $ids = $this->where($where)->column('id', 'id');
                return $ids ? array_flip_key_value($ids) : [];
            }
            catch (\Exception $e)
            {
                Log::write('FortuneNote model => ()异常：' . $e->getMessage() . '失败信息：' . $e->getFile() . ':' . $e->getLine(), 'error', true);
                return [];
            }
        });
        return $this->batchGetInfoByIds($ids);
    }

    /**
     * 今日是否记录心情笔记
     * @param int $uid
     * @param string $date
     * @return bool
     * @throws Exception
     */
    public function dateIsSetNote(int $uid, string $date)
    {
        $noteList = $this->getNoteLists($uid, 2);

        $time = strtotime($date);

        $noteDataTmp = array_column($noteList, null, 'time');

        return isset($noteDataTmp[$time]);
    }

    /**
     * 获取近几天的笔记
     * @param $type 1=>近7天  2=>近30天
     * @return array
     * @throws Exception
     */
    public function getInRecentDays($type)
    {
        $data = [
            1 => 0.0,
            2 => 0.0,
            3 => 0.0,
            4 => 0.0,
            5 => 0.0,
            6 => 0.0,
            7 => 0.0,
            8 => 0.0,
            9 => 0.0,
            10 => 0.0,
            11 => 0.0,
            12 => 0.0,
        ];
        try
        {
            $nowDate = date('Ymd');
            $data = CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('recent_info', $type . '-' . $nowDate)->setCacheTime(600)->getDataAndSet(function () use ($type, $data, $nowDate)
            {
                if ($type === 1)
                {
                    $times = Time::getNowTimeTimeRange($nowDate, '7');
                    $where['time'] = ['in', $times];
                } elseif ($type === 2)
                {
                    $times = Time::getNowTimeTimeRange($nowDate, '30');
                    $where['time'] = ['in', $times];
                }

                $where['tids'] = ['NEQ', ''];
                $where['sign_id'] = ['>', 0];

                //统计不同星座签到分数
                $noteDataScore = $this->where($where)->group('sign_id,mood')->field('sign_id,mood,count(id) num')->select();
                $noteDataScore = json_decode(json_encode($noteDataScore, true), true);
                if ($noteDataScore)
                {
                    //统计不同星座签到人数
                    $noteDataUser = $this->where($where)->group('sign_id')->field('sign_id,count(id) num')->select();
                    $noteDataUser = json_decode(json_encode($noteDataUser, true), true);
                    $noteDataUser = array_column($noteDataUser, null, 'sign_id');

                    $moodTagConfig = config('mood.mood_list');
                    //统计不同星座签到分数
                    foreach ($noteDataScore as $re)
                    {
                        $moodType = $moodTagConfig[$re['mood']]['type'];
                        // 5=>极好  4 不错   3 平平   2 沮丧  1 极差
                        if (in_array($moodType, [1, 2], false))
                        {
                            $score = 4 * $re['num'] / $noteDataUser[$re['sign_id']]['num'];
                        } elseif (in_array($moodType, [4, 5], false))
                        {
                            $score = 10 * $re['num'] / $noteDataUser[$re['sign_id']]['num'];
                        } else
                        {
                            $score = 6 * $re['num'] / $noteDataUser[$re['sign_id']]['num'];
                        }
                        $data[$re['sign_id']] += $score;
                    }
                }
                return $data;
            }, [], 'recent_info');
        }
        catch (\Exception $e)
        {
            Log::write('FortuneNote model => ()异常：' . $e->getMessage() . '失败信息：' . $e->getFile() . ':' . $e->getLine(), 'error', true);
        }
        $res = [];
        //指数处理
        foreach ($data as $signId => $score)
        {
            $res[] = [
                'sign_id' => $signId,
                'score' => number_format($score, 1)
            ];
        }
        //排序处理
        uksort($res, static function ($a, $b) use ($res)
        {
            if ($res[$a]['score'] == $res[$b]['score'])
            { // 如果值相同，则按照键正序排列
                return $a <=> $b;
            }
            // 否则，按照值倒序排列
            return $res[$b]['score'] <=> $res[$a]['score'];
        });
        return $res;
    }


    /**
     * 获取一段时间范围的笔记时间集(去重)
     * @param array $timeRange 时间戳数组集
     * @return array
     * @throws Exception
     */
    public function getTimeRangeNote($data, array $timeRange)
    {
        $res = [
            'mood_type_list' => [
                [
                    'color' => '#BAA8FE',
                    'name' => '负面情绪'
                ],
                [
                    'color' => '#F2EC3C',
                    'name' => '平静情绪'
                ],
                [
                    'color' => '#00E99C',
                    'name' => '正面情绪'
                ]
            ]
        ];
        $noteTimeData = [];
        $moodTagConfig = config('mood');
        foreach ($data as $datum)
        {
            if (isset($timeRange[$datum['time']]) && $timeRange[$datum['time']])
            {
                $moodType = $moodTagConfig['mood_list'][$datum['mood']]['type'];
                // 5=>极好  4 不错   3 平平   2 沮丧  1 极差
                if (in_array($moodType, [1, 2], false))
                {
                    $color = $res['mood_type_list'][0]['color'];
                } elseif (in_array($moodType, [4, 5], false))
                {
                    $color = $res['mood_type_list'][2]['color'];
                } else
                {
                    $color = $res['mood_type_list'][1]['color'];
                }
                $noteTimeData[] = [
                    'color' => $color,
                    'time' => date('Y-m-d', $datum['time']),
                    'mood' => $datum['mood'],
                    'sign_id' => $datum['sign_id'],
                ];
            }
        }
        $res['day_list'] = $noteTimeData;
        return $res;
    }

    /**
     * 获取排名信息
     * @param $rid
     * @param $noteData
     * @return array|array[]
     * @throws Exception
     */
    public function getNoteRank($rid, $noteData)
    {
        $signData = [];
        $selfSignUserNum = 0;//当前星座的签名数量
        $selfSignId = 0;//当前星座id
        if ($rid)
        {
            $recode = (new Recode)->getInfoById($rid);
            $selfSignId = explode('-', $recode['sun'])[0];
        }
        $moodTagConfig = config('mood.mood_list');
        foreach ($noteData as $re)
        {
            if ($re['sign_id'] == $selfSignId)
            {
                $selfSignUserNum++;
            }
            $moodType = $moodTagConfig[$re['mood']]['type'];
            // 5=>极好  4 不错   3 平平   2 沮丧  1 极差
            if (in_array($moodType, [1, 2], false))
            {
                $score = 4;
            } elseif (in_array($moodType, [4, 5], false))
            {
                $score = 10;
            } else
            {
                $score = 6;
            }
            if (isset($signData[$re['sign_id']]['score']))
            {
                $signData[$re['sign_id']]['score'] += $score;
                $signData[$re['sign_id']]['user_num'] += 1;
            } else
            {

                $signData[$re['sign_id']]['score'] = $score;
                $signData[$re['sign_id']]['user_num'] = 1;
            }
        }

        $data = [
            'today_rank' => [
                1 => 0.0,
                2 => 0.0,
                3 => 0.0,
                4 => 0.0,
                5 => 0.0,
                6 => 0.0,
                7 => 0.0,
                8 => 0.0,
                9 => 0.0,
                10 => 0.0,
                11 => 0.0,
                12 => 0.0,
            ],
            'self_rank' => 0,
            'self_sign' => 0,
            'self_sign_user_num' => $selfSignUserNum,
        ];

        //指数处理
        foreach ($signData as $singId => $signDatum)
        {
            $data['today_rank'][$singId] = number_format($signDatum['score'] / $signDatum['user_num'], 1);
        }
        //排序处理
        uksort($data['today_rank'], static function ($a, $b) use ($data)
        {
            if ($data['today_rank'][$a] == $data['today_rank'][$b])
            { // 如果值相同，则按照键正序排列
                return $a <=> $b;
            }
            // 否则，按照值倒序排列
            return $data['today_rank'][$b] <=> $data['today_rank'][$a];
        });
        $selfIndex = 0;
        $hasSelf = false;
        if (isset($recode))
        {
            foreach ($data['today_rank'] as $signId => $score)
            {
                $selfIndex++;
                if ($selfSignId == $signId)
                {
                    $hasSelf = true;
                    break;
                }
            }
            $data['self_rank'] = $hasSelf ? $selfIndex : 0;
            $data['self_sign'] = $selfSignId;
        }

        unset($data['today_rank'][0]);
        return $data;
    }

    /**
     * 获取今日心情签到信息
     * @param $uid
     * @return array|mixed
     * @throws Exception
     */
    public function checkTodayNoteStatus($uid)
    {
        if ($uid)
        {
            // 获取幸运星 领取信息
            $userLuckyChangeRecordModel = new AppUserLuckyChangeRecord();
            $date = date('Ymd');
            $signInInfo = $userLuckyChangeRecordModel->getUserSignInfoByToday($uid, $date);
            if ($signInInfo['num'] >= 10)
            {   // 已签到
                $noteInfo = $this->getNoteLists($uid, 2);
                $rankInfo = $noteInfo ? array_column($noteInfo, null, 'time') : [];
                $nowTimeTmp = strtotime(date('Y-m-d'));
                if (isset($rankInfo[$nowTimeTmp]))
                {   // 心情未删除
                    $moodTagConfig = config('mood.mood_list');
                    $resData = [
                        'mood_icon' => $moodTagConfig[$rankInfo[$nowTimeTmp]['mood']]['icon'] . '.png',
                        'mood_icon_s' => $moodTagConfig[$rankInfo[$nowTimeTmp]['mood']]['icon'] . '_s.png',
                        'mood_name' => $moodTagConfig[$rankInfo[$nowTimeTmp]['mood']]['name'],
                        'mood_type' => $moodTagConfig[$rankInfo[$nowTimeTmp]['mood']]['type'],
                    ];
                } else
                {   // 心情已删除
                    $resData = [
                        'mood_icon' => '',
                        'mood_icon_s' => '',
                        'mood_name' => '',
                        'mood_type' => '',
                    ];
                }
                return $resData;
            }
        }
        return [];
    }

    /**
     * 检查日运势解锁状态
     * @param int $uid
     * @param string $date 当前查看日期
     * @return array
     * @throws \Exception
     */
    public function CheckFortuneSevenUnlockStatus(int $uid, string $date): array
    {
        $time = strtotime($date);
        $time1 = strtotime('-3day', $time);
        $time2 = strtotime('-2day', $time);
        $time3 = strtotime('-1day', $time);
        $time4 = strtotime('+1day', $time);
        $time5 = strtotime('+2day', $time);
        $time6 = strtotime('+3day', $time);
        $times = [
            $time1 => $time1,
            $time2 => $time2,
            $time3 => $time3,
            $time => $time,
            $time4 => $time4,
            $time5 => $time5,
            $time6 => $time6
        ];
        $data = $this->getNoteLists($uid, 2);
        return $this->getTimeRangeNote($data, $times);
    }

    /**
     * 根据id批量获取运势笔记
     * @param $ids
     * @param $type
     * @param $sortType
     * @return array
     */
    public function getInfoByIdsInData($ids, $type, $sortType)
    {
        $ids = is_array($ids) ? $ids : explode(',', $ids);

        if (!empty($ids))
        {
            $where = ['id' => ['in', $ids]];
        } else
        {
            $where = ['uid' => $type[0], 'status' => ['>', -1]];
            $noteType = (int)$type[1];
            if ($noteType === 1)
            {
                $where['tids'] = '';
            } elseif ($noteType === 2)
            {
                $where['tids'] = ['NEQ', ''];
            }
        }
        try
        {
            $data = $this->where($where)->order('id', 'DESC')->column('*', 'id');
        }
        catch (Exception $e)
        {
            $data = [];
        }

        return $data;
    }

    public function batchGetInfoByIds($cids, $field = [])
    {
        $resData = parent::batchGetInfoByIds($cids, $field);
        foreach ($resData as $id => $dateItem)
        {
            $resData[$id] = arrayKeyData2int($dateItem, ['id', 'status', 'uid', 'rid', 'sign', 'time', 'state', 'mood', 'create_time', 'update_time']);

            if (!empty($dateItem['tids']))
            {
                $tids = explode(',', $dateItem['tids']);
                foreach ($tids as $k => $tid)
                {
                    $tids[$k] = (int)$tid;
                }
            } else
            {
                $tids = [];
            }
            $resData[$id]['tids'] = $tids;
        }

        return $resData;
    }
}
